type JsType = "Object" | "Array" | "Null" | "Undefined" | "String" | "Number" | "BigInt" | "Symbol";
const inspectType = (target: any, type: JsType) => {
    return Object.prototype.toString.call(target).slice(8, -1) === type;
}

const buildFormData = (formData: FormData, data: any, parentKey: any = null) => {
    if (inspectType(data, "Object")) {
        Object.keys(data).forEach(key => {
            buildFormData(formData, data[key], parentKey ? `${parentKey}.${key}` : key);
        });
    } else if (inspectType(data, "Array")) {
        data.forEach((item: any, i: any) => {
            if (!(item instanceof File) && !inspectType(item, "String")) {
                buildFormData(formData, item, `${parentKey}[${i}]`);
            } else {
                buildFormData(formData, item, `${parentKey}`);
            }
        });
    } else {
        const value = data == null ? "" : data;
        formData.append(parentKey, value);
    }
}

export const toFormData = (param: Record<string, any>) => {
    const formData = new FormData();
    buildFormData(formData, param);
    return formData;
};